package util;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.File;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 敏感词扫描工具类，可以扫描word, excel, pdf, txt里的敏感词
 * 依赖：
 * <pre>{@code
 * <dependency>
 * 	<groupId>com.itextpdf</groupId>
 * 	<artifactId>itextpdf</artifactId>
 * 	<version>5.5.13</version>
 * </dependency>
 * }</pre>
 * @author wanglei
 * @date 2019/5/21
 */
public class KeyWordScanUtil {

    /**
     * 关键词
     * */
    final private static String[] KEYWORD = {
            "一体化联合作战平台",
            "一体化作战平台",
            "一体化平台",
            "一体化",
            "教育职业技能培训学校",
            "教育转化培训中心",
            "职业技能培训中心",
            "民宗团结一家亲",
            "国民教育学校",
            "便民警务站",
            "清真寺优化",
            "拘押收教",
            "监控设施",
            "卫星工厂",
            "扶贫车间",
            "边境防控",
            "四同四送",
            "教转中心",
            "医疗救助",
            "驻寺管寺",
            "教育转化",
            "教培中心",
            "群众工作",
            "访惠聚",
            "驻村", "住村", "维稳", "教培", "秘密",
            "机密", "绝密", "收押", "收教", "收治", "案情", "招聘", "反恐", "防爆",
            "斋月",
            "支教",
            "保安", "稳定", "双语",
            "朝觐"
    };

    /**
     * 输出文件路径
     * */
    final private static String DEST_PATH = "D:\\tmp\\keyWord";
    /**
     * 检查结果文件名称
     * */
    final private static String CHECK_FILE_NAME = "关键词检查结果.txt";
    /**
     * 定义日志缓存
     * */
    private static StringBuilder logCache = new StringBuilder();
    /**
     * word 文件扩展名
     * */
    final private static List<String> WORD_SUFFIX_LIST = new ArrayList<>();
    /**
     * excel 文件扩展名
     * */
    final private static List<String> EXCEL_SUFFIX_LIST = new ArrayList<>();
    /**
     * pdf 文件扩展名
     * */
    final private static List<String> PDF_SUFFIX_LIST = new ArrayList<>();
    /**
     * 文本文件 文件扩展名
     * */
    final private static List<String> TXT_SUFFIX_LIST = new ArrayList<>();
    /**
     * 扫描输出的的文件夹名称
     * */
    private static String folderName = "xxx";

    static{
        WORD_SUFFIX_LIST.add("doc");
        WORD_SUFFIX_LIST.add("docx");

        EXCEL_SUFFIX_LIST.add("xls");
        EXCEL_SUFFIX_LIST.add("xlsx");

        PDF_SUFFIX_LIST.add("pdf");

        TXT_SUFFIX_LIST.add("txt");

        File directory = new File(DEST_PATH);
        directory.mkdirs();
    }

    // ------------------------------------公共方法----------------------------------------------------------//

    /**
     * 递归检查一个目录下的所有文件，结果打印到控制台
     * @param path 文件目录
     * */
    public static void recursiveCheckDirectory(String path){
        // 获取一个目录下的所有文件
        List<String> fileList = FileUtil.recursiveFileList(path);
        // 遍历文件
        if(fileList!=null && fileList.size()>0){
            for(String filePath : fileList){
                checkFile(filePath);
            }
        }
    }

    /**
     * 检查一个文件
     * @param filePath 文件路径
     * */
    public static void checkFile(String filePath){
        // 获取文件类型
        File file = new File(filePath);
        String fileNameSuffix = FileUtil.getFileNameSuffix(file.getName());
        // 根据文件类型调用不同文件类型的检查
        if(WORD_SUFFIX_LIST.contains(fileNameSuffix)){
            checkWord(filePath);
            annotationWord(filePath);
        }
        // excel
        else if(EXCEL_SUFFIX_LIST.contains(fileNameSuffix)){
            checkExcel(filePath);
        }
        // pdf
        else if(PDF_SUFFIX_LIST.contains(fileNameSuffix)){
            checkPdf(filePath);
        }
        // txt
        else if(TXT_SUFFIX_LIST.contains(fileNameSuffix)){

        }
        else{ // 不支持检查的文件类型
            System.out.println("不支持检查的文件类型");
        }
    }

    // ------------------------------------私有方法----------------------------------------------------------//

    /**
     * 检查一个word文件
     * @param filePath 文件路径
     * */
    private static void checkWord(String filePath){
        try {
            List<String> docContent = WordUtil.getWordText(filePath);
            List<String> allKeyList = new ArrayList<>();
            for(String content : docContent){
                List<String> currentContentKeyList = checkKeyWord(content);
                allKeyList.addAll(currentContentKeyList);
            }
            ListUtil.removeDuplicateWithOrder(allKeyList);
            if(allKeyList.size()>0){
                outPutMessage("[" + FileUtil.getFileName(filePath) + "]包含的关键词有：" + allKeyList.toString() + "\r\n");
            }
        } catch (Exception e) {
            System.out.println("获取word内容失败！！！word文件路径：" + filePath);
        }
    }



    /**
     * 检查一个excel文件
     * @param filePath 文件路径
     * */
    private static void checkExcel(String filePath){
        Workbook workbook = ExcelUtil.getExcelByPath(filePath);
        if(workbook!=null){
            Iterator<Sheet> sheetIterator = workbook.sheetIterator();
            while(sheetIterator.hasNext()){
                List<String> sheetKeyWordList = new ArrayList<>();
                Sheet sheet = sheetIterator.next();
                int rows = sheet.getPhysicalNumberOfRows();
                for(int i=0; i<rows; i++){
                    Row row = sheet.getRow(i);
                    if(row != null){
                        int columns = row.getPhysicalNumberOfCells();
                        for(int j=0; j<columns; j++){
                            Cell cell = row.getCell(j);
                            if(cell != null){
                                Object value = ExcelUtil.getCellValue(workbook, cell);
                                if(value != null){
                                    List<String> keyWord = checkKeyWord(value.toString());
                                    sheetKeyWordList.addAll(keyWord);
                                }
                            }
                        }
                    }
                }
                if (sheetKeyWordList.size() > 0){
                    outPutMessage("[" + FileUtil.getFileName(filePath) + "] "+"在工作簿"+ "[" + sheet.getSheetName() + "]：" + "包含敏感词" + sheetKeyWordList);
                }

            }
        }
    }


    /**
     * 检查一个pdf
     * @param fileName
     */
    public static void checkPdf(String fileName){
        String pageContent = "";
        String check ="没有发现";
        try {
            PdfReader reader = new PdfReader(fileName);
            int pageNum = reader.getNumberOfPages();
            for(int i=1;i<=pageNum;i++){
                //读取第i页的文档内容
                pageContent += PdfTextExtractor.getTextFromPage(reader, i);
            }
            checkKeyWord(pageContent);
            if (checkKeyWord(pageContent).size() > 0){
                check = "发现";
            }
            outPutMessage("\r\n"+"[" + FileUtil.getFileName(fileName) + "] "+ check +"敏感词：\r\n" + checkKeyWord(pageContent).toString() + "\r\n");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取Pdf内容失败！！！Pdf文件路径：" + fileName);
        }
    }
    // 检查一个txt文件

    // 替换一个文件

    /**
     * 替换一个word文件
     * @param filePath 文件路径
     * */
    private static void replaceWord(String filePath){
        String fileName = FileUtil.getFileName(filePath);
        String reportPath = DEST_PATH + "\\" + folderName + "\\处理关键词后的报告\\";
        File f = new File(reportPath);
        f.mkdirs();
        WordUtil.replaceWordContent(filePath, reportPath + fileName, KEYWORD, null);
    }

    /**
     * 给word文件加批注
     * @param filePath 文件路径
     */
    private static void annotationWord(String filePath){
        String fileName = FileUtil.getFileName(filePath);
        String reportPath = DEST_PATH + "\\" + folderName + "敏感词" + "\\处理关键词后的报告\\";
        File f = new File(reportPath);
        f.mkdirs();
        WordUtil.annotationWordContent(filePath, reportPath + fileName, KEYWORD);
    }

    /**
     * 格式化控制台输出和文件输出内容
     * */
    private static void outPutMessage(String message) {
        logCache.append(message).append("\r\n");
        System.out.println(message);
    }

    // ------------------------------------以前的方法----------------------------------------------------------//

    /**
     * 检查字符串包含的敏感词
     * @param str 需要检查的字符串
     * */
    private static List<String> checkKeyWord(String str){
        List<String> includeKeyWordList = new ArrayList<>();
        for(String key : KEYWORD){
            if(str.contains(key)){
                includeKeyWordList.add(key);
            }
        }
        return includeKeyWordList;
    }

    /**
     * 关键字扫描 单个doc地址
     * */
    public static void keyWordScan(String docPath) throws Exception {

        // 获取所有doc
        List<String> docContent = WordUtil.getWordText(docPath);
        String name = StringUtil.getFileNameByPath(docPath);
        List<String> queryResult = queryKeyWordByList(docContent, KEYWORD);
        if (queryResult != null && queryResult.size() > 0) {
            System.out.println("敏感词扫描结果：");
            logCache.append("\r\n[" + name + "] 敏感词扫描结果：\r\n\r\n");
        }
        for (String result : queryResult) {
            System.out.println("段落 " + result);
            logCache.append("段落 " + result + "\r\n");
        }
    }

    /**
     * 通过list查询关键字
     * */
    private static List<String> queryKeyWordByList(List<String> docContent, String[] keywordArray) {
        List<String> result = new ArrayList<>();
        // 遍历word每一个段落
        for (String wordPara : docContent) {
            // 将当前段落的换行符和首位空格删除
            wordPara = wordPara.replaceAll("[\r|\n]", " ");
            // 将当前段落分割为一个句子
            String[] sentenceArray = wordPara.split("[，\\|。\\|、\\|；]");
            for (String sentence : sentenceArray) {
                for (String key : keywordArray) {
                    if (sentence.contains(key)) {
                        result.add("[" + sentence + "] 包含敏感词：[" + key + "]");
                    }
                }
            }
        }
        return result;
    }

    /**
     * 获取所有预算报告doc目录
     * */
    private static List<String> getAllYuSuanDoc(String srcPath) {
        File fileSrcPath = new File(srcPath);
        File[] fileSrcPathArray = fileSrcPath.listFiles();
        // 所有文件
        List<String> allFilePath = new ArrayList<>();
        if (fileSrcPathArray != null) {
            for (File listFile : fileSrcPathArray) {
                // 递归查询原始目录里的所有文件目录
                List<String> srcFilePath = new ArrayList<>();
                recurveQuery(listFile, srcFilePath);
                allFilePath.addAll(srcFilePath);

            }
        }
        return allFilePath;
    }

    /**
     * 递归查询一个文件里的所有文件，.doc, docx, docm, xls, .xlsx
     * */
    private static void recurveQuery(File file, List<String> fileList) {
        String fileName = file.getName();
        boolean docFlag = Pattern.matches(".*(\\.doc[x|m]?)", fileName);
        // 如果是文件，且是.doc, docx, docm, xls, .xlsx, 添加
        if (file.isFile() && (docFlag)) {
            fileList.add(file.getAbsolutePath());
        }
        // 如果是目录，递归查询
        if (file.isDirectory()) {
            File[] listFiles = file.listFiles();
            if (listFiles != null) {
                for (File listFile : listFiles) {
                    recurveQuery(listFile, fileList);
                }
            }
        }
    }
}
